package com.projectsexception.festivales.setup;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.os.Environment;

import com.projectsexception.festivales.provider.exceptions.ParserException;
import com.projectsexception.festivales.provider.handlers.BandsHandler;
import com.projectsexception.festivales.provider.handlers.FeedsHandler;
import com.projectsexception.festivales.provider.handlers.InfoHandler;
import com.projectsexception.festivales.provider.handlers.MapsHandler;
import com.projectsexception.festivales.provider.handlers.ShowsHandler;
import com.projectsexception.festivales.provider.handlers.StagesHandler;
import com.projectsexception.festivales.provider.model.Band;
import com.projectsexception.festivales.provider.model.FeedFestival;
import com.projectsexception.festivales.provider.model.Info;
import com.projectsexception.festivales.provider.model.MapFestival;
import com.projectsexception.festivales.provider.model.Show;
import com.projectsexception.festivales.provider.model.Stage;
import com.projectsexception.festivales.provider.util.SAXHandlerUtil;

public final class ProjectResources {
    
    public static final String APP_DIR = "/festivales/";
    public static final String BANDS_FILE = "bands.xml";
    public static final String FEEDS_FILE = "news.xml";
    public static final String INFO_FILE = "info.xml";
    public static final String MAPS_FILE = "maps.xml";
    public static final String SHOWS_FILE = "shows.xml";
    public static final String STAGES_FILE = "stages.xml";

    private static ProjectResources myResources;
    
    private List<MapFestival> maps;
    private List<FeedFestival> feeds;
    private Map<String, Show> shows;
    private Map<String, Stage> stages;
    private Map<String, Band> bands;
    private List<Info> infos;
    private List<Date> showDates;
    private File xmlDir;
    
    public static ProjectResources initialize(Context context, String dirName) throws ConfigurationException {
        myResources = new ProjectResources(context, dirName);
        return myResources;
    }
    
    public static ProjectResources getInstance() {
        if (myResources == null) {
            throw new IllegalStateException("ProjectsResources not initialized");
        }
        return myResources;
    }
        
    private ProjectResources(Context context, String dirName) throws ConfigurationException {
        Context appContext = context.getApplicationContext();

        String rootDir = null;
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            // SD-card available
            rootDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/"
                    + appContext.getPackageName() + "/cache";
        } else {
            File internalCacheDir = appContext.getCacheDir();
            // apparently on some configurations this can come back as null
            if (internalCacheDir == null) {
                throw new ConfigurationException("No output directory avaible");
            } else {
                rootDir = internalCacheDir.getAbsolutePath();
            }
        }
        
        if (rootDir != null) {
            xmlDir = new File(rootDir + APP_DIR + dirName);
            if (!xmlDir.exists()) {
                xmlDir.mkdirs();
            }
        }
    }
    
    public File getXMLDir() {
        return xmlDir;
    }
    
    public Collection<Info> getInfos() {
        if (infos == null) {
            try {
                loadInfos();
            } catch (FileNotFoundException e) {
                
            } catch (ParserException e) {
                
            }
        }
        return infos;
    }
    
    public void loadInfos() throws FileNotFoundException, ParserException {
        InfoHandler handler = new InfoHandler();
        FileInputStream stream = new FileInputStream(new File(xmlDir, INFO_FILE));
        SAXHandlerUtil.launchHandler(stream, handler);
        infos = handler.getResult();
    }
    
    public Collection<MapFestival> getMaps() {
        if (maps == null) {
            try {
                loadMaps();
            } catch (FileNotFoundException e) {
                
            } catch (ParserException e) {
                
            }
        }
        return maps;
    }

    public void loadMaps() throws FileNotFoundException, ParserException {
        MapsHandler handler = new MapsHandler();
        FileInputStream stream = new FileInputStream(new File(xmlDir, MAPS_FILE));
        SAXHandlerUtil.launchHandler(stream, handler);
        maps = handler.getResult();
    }
    
    public Collection<FeedFestival> getFeeds() {
        if (feeds == null) {
            try {
                loadFeeds();
            } catch (FileNotFoundException e) {
                
            } catch (ParserException e) {
                
            }
        }
        return feeds;
    }

    public void loadFeeds() throws FileNotFoundException, ParserException {
        FeedsHandler handler = new FeedsHandler();
        FileInputStream stream = new FileInputStream(new File(xmlDir, FEEDS_FILE));
        SAXHandlerUtil.launchHandler(stream, handler);
        feeds = handler.getResult();
    }
    
    public Show getShow(String id) {
        if (shows == null) {
            try {
                loadShows();
            } catch (FileNotFoundException e) {
                
            } catch (ParserException e) {
                
            }
        }
        return shows.get(id);
    }
    
    public void loadShows() throws FileNotFoundException, ParserException {
        if (bands == null) {
            loadBands();
        }
        if (stages == null) {
            loadStages();            
        }
        ShowsHandler handler = new ShowsHandler(bands, stages);
        FileInputStream stream = new FileInputStream(new File(xmlDir, SHOWS_FILE));
        SAXHandlerUtil.launchHandler(stream, handler);
        shows = handler.getResult();
    }

    public Collection<Show> getShows() {
        if (shows == null) {
            try {
                loadShows();
            } catch (FileNotFoundException e) {
                
            } catch (ParserException e) {
                
            }
        }
        return shows.values();
    }
    
    public List<Date> getShowDates() {
        if (showDates == null) {
            loadShowDates();
        }
        return showDates;
    }

    private void loadShowDates() {
        if (shows == null) {
            try {
                loadShows();
            } catch (FileNotFoundException e) {
                
            } catch (ParserException e) {
                
            }
        }
        showDates = new ArrayList<Date>();
        for (Show show : shows.values()) {
            if (!showDates.contains(show.getDate())) {
                showDates.add(show.getDate());
            }
        }        
    }

    public List<Show> getShowsInDate(Date actualDate) {
        List<Show> showsList = new ArrayList<Show>();
        if (shows == null) {
            try {
                loadShows();
            } catch (FileNotFoundException e) {
                
            } catch (ParserException e) {
                
            }
        }
        for (Show show : shows.values()) {
            if (show.getDate().equals(actualDate)) {
                showsList.add(show);
            }
        }
        return showsList;
    }
    
    public Collection<Stage> getStages() {
        if (stages == null) {
            try {
                loadStages();
            } catch (FileNotFoundException e) {
                
            } catch (ParserException e) {
                
            }
        }
        return stages.values();
    }

    public void loadStages() throws FileNotFoundException, ParserException {
        StagesHandler handler = new StagesHandler();
        FileInputStream stream = new FileInputStream(new File(xmlDir, STAGES_FILE));
        SAXHandlerUtil.launchHandler(stream, handler);
        stages = handler.getResult();
    }
    
    public Collection<Band> getBands() {
        if (bands == null) {
            try {
                loadBands();
            } catch (FileNotFoundException e) {
                
            } catch (ParserException e) {
                
            }
        }
        return bands.values();
    }

    public void loadBands() throws FileNotFoundException, ParserException {
        BandsHandler handler = new BandsHandler("");
        FileInputStream stream = new FileInputStream(new File(xmlDir, BANDS_FILE));
        SAXHandlerUtil.launchHandler(stream, handler);
        bands = handler.getResult();
    }

}
